﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Workflow.Activities;
using Microsoft.Crm.Workflow;
using System.Workflow.ComponentModel;
using Microsoft.Crm.Sdk;
using System.Diagnostics;
using Microsoft.Crm.Sdk.Query;
using Microsoft.Crm.SdkTypeProxy;
using System.Web.Services.Protocols;

namespace Infusion.CRM.WF.CRM40DistributeWF
{

    /// <summary>
    /// Custom base class for all Sequence Activities.
    /// </summary>
    public abstract class SequenceActivityBase : SequenceActivity
    {

        /// <summary>
        /// We cannot serialize SequenceActivity if they have member variables, so we use this class to maintain status
        /// </summary>
        public class Context
        {

            #region Properties

            /// <summary>
            /// Primary Key of the entity the WF runs on.
            /// </summary>
            public Guid CurrentRecordId { get; set; }

            /// <summary>
            /// Name of the entity the WF runs on.
            /// </summary>
            public string CurrentEntityName { get; set; }

            /// <summary>
            /// Operation that triggered the workflow.
            /// </summary>
            public string CurrentOperation { get; set; }

            /// <summary>
            /// CRM Web Service.
            /// </summary>
            public ICrmService SvcHandle;

            /// <summary>
            /// CRM Metadata Service.
            /// </summary>
            public IMetadataService SvcMetadataHandle;

            #endregion

        }

        #region Workflow Properties

        /// <summary>
        /// Output Parameter: True if operation was successful. If False, Error Message will be populated.
        /// </summary>
        public abstract CrmBoolean Success { get; set; }

        /// <summary>
        /// Output Parameter: Error Message is only populated when Success == false.
        /// </summary>
        public abstract string ErrorMsg { get; set; }

        #endregion

        #region SequenceActivity

        /// <summary>
        /// Workflow step.
        /// </summary>
        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            try
            {
                IContextService contextService = (IContextService)executionContext.GetService(typeof(IContextService));
                Context context = new Context();

                context.CurrentRecordId = contextService.Context.PrimaryEntityId;
                context.CurrentOperation = contextService.Context.MessageName;
                context.CurrentEntityName = contextService.Context.PrimaryEntityName;
                context.SvcHandle = contextService.Context.CreateCrmService();
                context.SvcMetadataHandle = contextService.Context.CreateMetadataService();

                // Execute the actual workflow step body
                string errorMsg;
                this.Success = ExecuteBody(context, out errorMsg);
                this.ErrorMsg = errorMsg;
            }
            catch (SoapException ex)
            {
                Trace.WriteLine(ex.ToString());
                Trace.WriteLine(ex.Detail.InnerText);
                this.ErrorMsg = ex.Detail.InnerText;
                this.Success = new CrmBoolean(false);
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.ToString());
                this.ErrorMsg = ex.Message;
                this.Success = new CrmBoolean(false);
            }

            return ActivityExecutionStatus.Closed;
        }

        /// <summary>
        /// Overridden in derived classes: contains the actual workflow step.
        /// </summary>
        protected abstract CrmBoolean ExecuteBody(Context context, out string errorMsg);

        #endregion

    }

}
